﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Description;
using Microsoft.ServiceBus;
using nwrole.lib;
using nwrole.toolbox.sync.contract;
using nwrole.toolbox.sync.service;
using System.ServiceModel;

namespace nwrole.toolbox.sync.ServiceHost
{
    public class SyncDestinationServiceHost
    {
        private System.ServiceModel.ServiceHost host;

        public SyncDestinationServiceHost()
        {
            // EventLogger.LogInformation("BackOfficeServiceHostSyncPlugin", "Constructor");
        }

        public void Start(ServiceConnectionInfo connInfo, string dstDbConStr)
        {
            if (connInfo.Type == ServiceConnectionInfo.ServiceConnectionType.ServiceBus)
                StartServiceBus(connInfo, dstDbConStr);
            else
                StartWebService(connInfo, dstDbConStr);
        }

        public void StartServiceBus(ServiceConnectionInfo connInfo, string dstDbConStr)
        {
            ServiceBusEnvironment.SystemConnectivity.Mode = ConnectivityMode.AutoDetect;

            TransportClientEndpointBehavior sharedSecretServiceBusCredential = new TransportClientEndpointBehavior();
            sharedSecretServiceBusCredential.TokenProvider = TokenProvider.CreateSharedSecretTokenProvider(connInfo.ServiceBusIssuerName, connInfo.ServiceBusIssuerSecret);

            Uri baseAddress = ServiceBusEnvironment.CreateServiceUri("sb", connInfo.ServiceBusServiceNamespace, connInfo.ServiceBusServicePath);

            host = new System.ServiceModel.ServiceHost(typeof(SyncDestinationService), baseAddress);
            try
            {
                host.Description.Behaviors.Add(new ParamServiceBehavior<SyncDestServiceParams>(new SyncDestServiceParams(dstDbConStr, DataProviderType.Sql)));

                IEndpointBehavior serviceRegistrySettings = new ServiceRegistrySettings(DiscoveryType.Public);

                ContractDescription contractDescription = ContractDescription.GetContract(typeof(ISyncDestinationService), typeof(SyncDestinationService));
                ServiceEndpoint serviceEndPoint = new ServiceEndpoint(contractDescription);
                serviceEndPoint.Address = new EndpointAddress(baseAddress);
                //serviceEndPoint.Binding = new NetTcpRelayBinding();
                serviceEndPoint.Binding = new NetTcpRelayBinding(EndToEndSecurityMode.Transport, RelayClientAuthenticationType.RelayAccessToken);
                host.Description.Endpoints.Add(serviceEndPoint);

                foreach (ServiceEndpoint endpoint in host.Description.Endpoints)
                {
                    endpoint.Behaviors.Add(serviceRegistrySettings);
                    endpoint.Behaviors.Add(sharedSecretServiceBusCredential);
                }

                host.Opening += new EventHandler(serviceHost_Opening);
                host.Faulted += new EventHandler(serviceHost_Faulted);
                host.Opened += new EventHandler(serviceHost_Opened);
                host.Closed += new EventHandler(serviceHost_Closed);
                host.UnknownMessageReceived += new EventHandler<System.ServiceModel.UnknownMessageReceivedEventArgs>(serviceHost_UnknownMessageReceived);

                host.Open();

                Console.WriteLine("Service address: {0}", baseAddress);
            }
            catch (CommunicationException ce)
            {
                Console.WriteLine("An exception occurred with place {0}: {1}", "myplace", ce.Message);
                host.Abort();
            }
        }

        // "net.msmq://localhost/private/ServiceModelSamplesTransacted"
        //public System.ServiceModel.ServiceHost Open(string serviceBaseAddress, string servicePath, string destinationConnectionString)
        private void StartWebService(ServiceConnectionInfo connInfo, string dstDbConStr)
        {
            // EventLogger.LogInformation("BackOfficeServiceHostSyncPlugin", "Open");

            // Create a ServiceHost for the OrderProcessorService type.
            // Uri tcpBaseAddress = new Uri("net.tcp://localhost:9000/");
            // Uri tcpBaseAddress = new Uri("http://nefapp22:9000/");
            // Uri tcpBaseAddress = new Uri("http://localhost:9000/");

            //Uri tcpBaseAddress = new Uri("http://localhost:9004/");
            Uri tcpBaseAddress = new Uri("http://" + connInfo.WebServiceBaseAddress);

            host = new System.ServiceModel.ServiceHost(typeof(SyncDestinationService), tcpBaseAddress);
            host.Description.Behaviors.Add(new ParamServiceBehavior<SyncDestServiceParams>(new SyncDestServiceParams(dstDbConStr, DataProviderType.Sql)));

            // endpoint1 binding 1
/*            System.ServiceModel.EndpointAddress endpoint1 = new System.ServiceModel.EndpointAddress(queueName);
            System.ServiceModel.NetMsmqBinding binding1 = new System.ServiceModel.NetMsmqBinding();
            binding1.Security.Mode = System.ServiceModel.NetMsmqSecurityMode.None;
            binding1.MaxReceivedMessageSize = 2000000;
            binding1.Security.Transport.MsmqAuthenticationMode = System.ServiceModel.MsmqAuthenticationMode.None;

            serviceHost.Description.Endpoints.Add(
                new System.ServiceModel.Description.ServiceEndpoint(System.ServiceModel.Description.ContractDescription.GetContract(typeof(ISyncSyncService)),
                binding1, endpoint1)
            ); */

            // binding 2
            //EndpointAddress endpoint2 = new System.ServiceModel.EndpointAddress("http://localhost:9004/hejsan.svc");
            EndpointAddress endpoint2 = new System.ServiceModel.EndpointAddress(tcpBaseAddress + connInfo.WebServiceAddress);
            BasicHttpBinding binding2 = new System.ServiceModel.BasicHttpBinding(BasicHttpSecurityMode.None);
            binding2.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
            binding2.MaxBufferSize = 2147483647;
            binding2.MaxReceivedMessageSize = 2147483647;
            host.Description.Endpoints.Add(
                new ServiceEndpoint(ContractDescription.GetContract(typeof(ISyncDestinationService)),
                binding2, endpoint2)
            );


            // add mex endpoint
            System.ServiceModel.Description.ServiceMetadataBehavior metadataBehavior;
            metadataBehavior = host.Description.Behaviors.Find<System.ServiceModel.Description.ServiceMetadataBehavior>();
            if (metadataBehavior == null)
            {
                metadataBehavior = new System.ServiceModel.Description.ServiceMetadataBehavior();
                host.Description.Behaviors.Add(metadataBehavior);
            }

            // System.ServiceModel.Description.Net
            System.ServiceModel.Channels.BindingElement bindingElement = new System.ServiceModel.Channels.TcpTransportBindingElement();
            System.ServiceModel.Channels.CustomBinding binding3 = new System.ServiceModel.Channels.CustomBinding(bindingElement);

            // serviceHost.AddServiceEndpoint(typeof(IMetadataExchange), binding2, "MEX");
            host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex");

            host.Opening += new EventHandler(serviceHost_Opening);
            host.Faulted += new EventHandler(serviceHost_Faulted);
            host.Opened += new EventHandler(serviceHost_Opened);
            host.Closed += new EventHandler(serviceHost_Closed);
            host.UnknownMessageReceived += new EventHandler<System.ServiceModel.UnknownMessageReceivedEventArgs>(serviceHost_UnknownMessageReceived);

            host.Open();
            
            // EventLogger.LogInformation("BackOfficeServiceHostSyncPlugin", "Done");
        }

        public void Close()
        {
            host.Close();
        }

        void serviceHost_Opened(object sender, EventArgs e)
        {
            // EventLogger.LogInformation("BackOfficeServiceHostSyncPlugin", "serviceHost_Opened");
        }

        void serviceHost_Opening(object sender, EventArgs e)
        {
            // EventLogger.LogInformation("BackOfficeServiceHostSyncPlugin", "serviceHost_Opening");
        }

        void serviceHost_UnknownMessageReceived(object sender, System.ServiceModel.UnknownMessageReceivedEventArgs e)
        {
            // EventLogger.LogInformation("BackOfficeServiceHostSyncPlugin", "serviceHost_UnknownMessageReceived");
        }

        void serviceHost_Faulted(object sender, EventArgs e)
        {
            // EventLogger.LogInformation("BackOfficeServiceHostSyncPlugin", "serviceHost_Faulted");
        }

        void serviceHost_Closed(object sender, EventArgs e)
        {
            // EventLogger.LogInformation("BackOfficeServiceHostSyncPlugin", "serviceHost_Faulted");
        }
    }
}
